package com.flex.mobile.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.flex.mobile.dao.impl.TimerDao;
import com.flex.mobile.dao.model.TaxiTimer;
import com.flex.mobile.exception.TaxiException;
import com.flex.mobile.service.TimerService;
import com.flex.mobile.timer.OnceTimer;
import com.flex.mobile.timer.OnceTimerHandler;
import com.flex.mobile.timer.TimerConfig;
import com.flex.mobile.timer.TimerHandler;
import com.flex.mobile.timer.TimerHandlerSet;
import com.flex.mobile.timer.TimerLoader;
import com.flex.mobile.util.CalenderUtil;
import com.flex.mobile.util.StringUtil;

@Service("timerService")
public class TimerServiceImpl implements TimerService {
   private TimerDao timerDao;

   @Autowired
   public void setTimerDao(TimerDao timerDao) {
      this.timerDao = timerDao;
   }

   TimerHandler timerHandler = null;

   OnceTimer onceTimer = OnceTimer.getInstance();

   TimerLoader loader;

   public String getTimerString() {
      if (onceTimer == null) {
         return "Timer not start yet";
      } else {
         return onceTimer.logInnerTimerContent();
      }
   }

   public void startTimer() throws TaxiException {
      if (timerHandler == null) {
         throw new TaxiException("21094501");
      }

      TimerConfig.init();
      loader = new TimerLoader(onceTimer);
      loader.start();
      onceTimer.setHandler(new OnceTimerHandler() {
         public void timerTrigged(long key) {
            TaxiTimer timer = null;
            try {
               try {
                  timer = modifyTimerState(key);
               } finally {
               }
            } catch (Exception e) {
               e.printStackTrace();
               return;
            }

            if (timer == null)
               return;

            timerHandler.handlerTimer(timer);
         }

         public TaxiTimer modifyTimerState(long key) throws Exception {
            TaxiTimer curTimer = timerDao.findById(key);

            if (!TaxiTimer.STAT_ACTIVE.equals(curTimer.getCurrentState())) {
               return null;
            }

            if (curTimer.getTimerType().equals(TaxiTimer.TYPE_ONCE)) {
               curTimer.setCurrentState(TaxiTimer.STAT_ENDED);
               timerDao.update(curTimer);
            } else {
               curTimer.setCycleTimes(curTimer.getCycleTimes() - 1);

               if (curTimer.getCycleTimes() > 0) {
                  curTimer.setNextTriggeTime(curTimer.getNextTriggeTime()
                        + curTimer.getCycleInterval());
                  timerDao.update(curTimer);
                  onceTimer.registeTimer(curTimer.getTimerID(),
                        curTimer.getNextTriggeTime());
               } else {
                  curTimer.setCurrentState(TaxiTimer.STAT_ENDED);
                  timerDao.update(curTimer);
               }
            }

            return curTimer;
         }
      });
      onceTimer.startTimer();
   }

   public synchronized void registeTimerHandler(TimerHandler timerHandler) {
      if (this.timerHandler == null)
         this.timerHandler = new TimerHandlerSet();
      ((TimerHandlerSet) this.timerHandler)
            .setDefaultTimerHandler(timerHandler);
   }

   public int registeTimer(String timerKind, String objectID, String timerName,
         String parameter, long trigTime) throws TaxiException {
      TaxiTimer timer = new TaxiTimer();

      timer.setTimerType(TaxiTimer.TYPE_ONCE);
      timer.setTimerKind(timerKind);
      timer.setObjectID(objectID);
      timer.setTimerName(timerName);
      timer.setParameter(parameter);
      timer.setCurrentState(TaxiTimer.STAT_ACTIVE);
      timer.setRegisteTime(CalenderUtil.getCurrentTime());
      timer.setFirstTriggeTime(trigTime);
      timer.setNextTriggeTime(trigTime);

      timerDao.create(timer);

      if (loader.getNextLoadTime() >= timer.getFirstTriggeTime())
         this.onceTimer.registeTimer(timer.getTimerID(),
               timer.getNextTriggeTime());
      return 1;
   }

   public int unregisteTimer(String timerKind, String objectID)
         throws TaxiException {
      while (true) {
         List<TaxiTimer> tarr = timerDao.findTimerByObjectId(timerKind, objectID);
         if (tarr.size() == 0)
            break;

         for (int i = 0; i < tarr.size(); i++) {
            timerDao.remove(tarr.get(i));
            this.onceTimer.unregisteTimer(tarr.get(i).getTimerID());
         }
      }

      return 0;
   }

   public int unregisteTimer(String timerID) throws TaxiException {
      if (StringUtil.isNull(timerID)) {
         return 0;
      }
      TaxiTimer tarr = timerDao.findById(Long.parseLong(timerID));
      timerDao.remove(tarr);
      return 1;
   }

   public int suspendTimer(String timerKind, String objectID, int time)
         throws TaxiException {
      throw new TaxiException("");
   }

   public int suspendTimer(int timerID, int time) throws TaxiException {
      throw new TaxiException("");
   }

   public int resumeTimer(String timerKind, String objectID, int time)
         throws TaxiException {
      throw new TaxiException("");
   }

   public int resumeTimer(int timerID, int time) throws TaxiException {
      throw new TaxiException("");
   }

   public long registeCycleTimer(String timerKind, String objectID,
         String timerName, String parameter, long firstTrigTime, long interval,
         int trigTimes) throws TaxiException {
      TaxiTimer timer = new TaxiTimer();

      if (!(trigTimes >= 1))
         throw new TaxiException("");

      timer.setTimerType(TaxiTimer.TYPE_CYCLE);
      timer.setTimerKind(timerKind);
      timer.setObjectID(objectID);
      timer.setTimerName(timerName);
      timer.setParameter(parameter);
      timer.setCurrentState(TaxiTimer.STAT_ACTIVE);
      timer.setRegisteTime(CalenderUtil.getCurrentTime());
      timer.setFirstTriggeTime(firstTrigTime);
      timer.setNextTriggeTime(firstTrigTime);
      timer.setCycleTimes(trigTimes);
      timer.setCycleInterval(interval);
      timerDao.create(timer);
      this.onceTimer
            .registeTimer(timer.getTimerID(), timer.getNextTriggeTime());
      return timer.getTimerID();
   }

   public long queryTimerFirstTrigTime(String timerKind, String objectID)
         throws TaxiException {
      List<TaxiTimer> list = timerDao.findTimerByObjectId(timerKind, objectID);
      if (list == null || list.size() == 0)
         return 0;
      else
         return list.get(0).getFirstTriggeTime();
   }

   public void stopTimer() {
      loader.stop();
   }

   public void clearEndedTimer() {
      timerDao.deleteEndedTimer();
   }
}
